package com.linked.store.thing.controller;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.itextpdf.text.pdf.parser.clipper.Path;
import com.linked.store.thing.bean.param.AddThingParam;
import com.linked.store.thing.bean.param.ThingPageParam;
import com.linked.store.thing.bean.po.ThingImagesPO;
import com.linked.store.thing.bean.vo.ThingInfoVO;
import com.linked.store.thing.bean.vo.ThingPageVO;
import com.linked.store.thing.service.IThingHandleService;
import com.linked.store.util.MinioUtils;
import com.linked.universal.common.LinkedPrompt;
import com.linked.universal.common.LinkedResult;
import com.linked.universal.common.Result;
import lombok.extern.slf4j.Slf4j;
import org.apache.http.entity.ContentType;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.util.List;
import java.util.concurrent.TimeUnit;

/**
 * @author :dbq
 * @date : 2023/3/17 14:01
 * @description : desc
 */
@RestController
@RequestMapping("thinghandle")
@Slf4j
public class ThingHandleController {

    private final ObjectMapper mapper;

    private final IThingHandleService thingHandleService;

    private final MinioUtils minioUtils;

    private final StringRedisTemplate redisTemplate;

    @Autowired
    public ThingHandleController(StringRedisTemplate redisTemplate, ObjectMapper mapper, IThingHandleService thingHandleService, MinioUtils minioUtils) {
        this.mapper = mapper;
        this.thingHandleService = thingHandleService;
        this.minioUtils = minioUtils;
        this.redisTemplate = redisTemplate;
    }

    @PostMapping("addThingInfo")
    Result addThingInfo(@RequestBody AddThingParam param) throws Exception {
        if (log.isInfoEnabled()) {
            log.info("添加物品接口 入参：{}", mapper.writeValueAsString(param));
        }
        boolean ret = false;
        try {
            ret = thingHandleService.addThingInfo(param);
        } catch (Exception e) {
            log.error("添加物品接口 异常", e);
            return Result.error("出现未知错误，请联系管理员");
        }
        return ret ? Result.success() : Result.ok(false, "添加失败！");
    }

    @PostMapping("queryThingListByBoxId")
    Result queryThingListByBoxId(String boxId) throws Exception {
        if (log.isInfoEnabled()) {
            log.info("根据收纳箱查询物品列表接口 入参：" + boxId);
        }
        List<ThingInfoVO> resList = null;
        try {
            resList = thingHandleService.queryThingListByBoxId(boxId);
        } catch (Exception e) {
            log.error("根据收纳箱查询物品列表接口 异常", e);
            return Result.error("出现未知错误，请联系管理员");
        }
        return !CollectionUtils.isEmpty(resList) ? Result.success(resList) : Result.ok(false, "未查询到数据！");
    }

    @PostMapping("queryThingPage")
    Result queryThingPage(@RequestBody ThingPageParam param) throws Exception {
        if (log.isInfoEnabled()) {
            log.info("查询物品页面接口 入参：{}", mapper.writeValueAsString(param));
        }
        IPage<ThingPageVO> page = null;
        try {
            page = thingHandleService.queryThingPage(param);
        } catch (Exception e) {
            log.error("查询物品页面接口 异常", e);
            return Result.error("出现未知错误，请联系管理员");
        }
        return page != null ? Result.success(page) : Result.ok(false, "未查询到数据！");
    }

    @PostMapping("uploadThingImage")
    Result uploadThingImage(MultipartFile mutiFile, String thingId) throws Exception {
        if (log.isInfoEnabled()) {
            log.info("上传物品图片接口 入参：" + thingId);
        }
        String imageUrl = null;
        try {
            imageUrl = minioUtils.uploadFile(new ByteArrayInputStream(mutiFile.getBytes()), mutiFile.getOriginalFilename(), "thing_image");
        } catch (IOException e) {
            log.error("上传物品图片接口 异常", e);
            return Result.error("出现未知错误，请联系管理员");
        }
        if (StringUtils.isEmpty(imageUrl)) {
            return Result.ok(false, "上传失败！");
        }
        ThingImagesPO thingImages = new ThingImagesPO();
        thingImages.setThingId(thingId);
        thingImages.setImageName(mutiFile.getOriginalFilename());
        thingImages.setImageUrl(imageUrl);
        try {
            boolean ret = thingHandleService.uploadThingImage(thingImages);
            if (!ret) {
                log.info("保存物品图片关系失败！");
                return Result.ok(false, "上传失败！");
            }
        } catch (Exception e) {
            log.error("上传物品图片接口-保存物品图片关系 异常", e);
            return Result.error("出现未知错误，请联系管理员");
        }
        return Result.success(imageUrl);

    }

    @PostMapping("reduceInventory")
    LinkedResult reduceInventory(@RequestParam String orderId, @RequestParam String goodsVersionId, @RequestParam int goodsCount) throws InterruptedException {
        if (log.isInfoEnabled()) {
            log.info("扣减库存借口 goodsVersionId：" + goodsVersionId + "  商品数量:" + goodsCount);
        }

        /**
         * 一、查询某一商品数量总数
         * */
        Integer thingCount = thingHandleService.findThingsCount(goodsVersionId);
        if (thingCount == null) {
            return LinkedResult.CheckFailure(LinkedPrompt.NO_QUERY_GOODS);
        }
        if (thingCount - goodsCount <= 0) {
            return LinkedResult.CheckFailure(LinkedPrompt.GOODS_SELL_OUT);
        }
        /**
         * 二、扣减缓存库存
         * */
        String redisKey = "ThingCount_" + goodsVersionId;
        redisTemplate.opsForValue().decrement(redisKey, goodsCount);
        /**
         * 三、生成排队的号
         * 在支付完成以后，会校验这个号
         * */
        String redisKey_lineUp = "GoodsLine_" + goodsVersionId + "_" + orderId;
        redisTemplate.opsForValue().set(redisKey_lineUp, "value", 30, TimeUnit.MINUTES);
        /**
         * 四、延长扣减库存后的key有效时限
         * */
        redisTemplate.expire(redisKey, 30, TimeUnit.MINUTES);

        return LinkedResult.Success();
    }
}
